import maplibregl from 'maplibre-gl';

const TAG_COLORS = {
	rock: '#d90429', // 鲜红
	jazz: '#008080', // 孔雀绿
	pop: '#ff1493', // 深粉红
	folk: '#1e90ff', // 天空蓝
	classical: '#6a0dad', // 紫罗兰
	rap: '#ffa500', // 橙色
	rnb: '#9400d3', // 深紫
	electric: '#00ffff', // 青色
	news: '#ff4500', // 橘红
	talk: '#6d6875', // 深灰紫（代表对话冷静气质）
	ambient: '#a8dadc', // 柔蓝绿（氛围平静感）
	world: '#2a9d8f', // 深绿蓝（全球文化感）
	default: '#c0c0c0' // 默认灰
}
const CATEGORY_REGEX_MAP = {
	rock: /rock|rock[-\s]?pop|rock[’']?n[’']?roll/i,
	jazz: /jazz|smooth\s*jazz|acid\s*jazz/i,
	pop: /(?:^|[^a-z])pop(?:[^a-z]|$)|k[-\s]?pop|j[-\s]?pop/i,
	folk: /folk|indie\s*folk|americana/i,
	classical: /classical|orchestra|symphony|baroque|chamber/i,
	rap: /rap|hip[-\s]?hop|hiphop|trap/i,
	rnb: /r[\s&]*b|rnb|rhythm\s+and\s+blues/i,
	electric: /electro|electric|edm|techno|house|dance/i,
	news: /news|broadcast|public\s*radio|current\s*affairs/i,
	talk: /talk|talk\s*radio|discussion|interview/i,
	ambient: /ambient|downtempo|lofi|atmospheric/i,
	world: /world|global|ethnic|international|latin|afro|reggae|caribbean/i
};


function normalizeCategory(rawTags = '') {
	const cleaned = rawTags.replace(/[#"']/g, '').toLowerCase();
	for (const [category, regex] of Object.entries(CATEGORY_REGEX_MAP)) {
		if (regex.test(cleaned)) return category;
	}
	return 'default';
}

const languageMap = {
	CN: ['zh', 'chinese', 'mandarin', 'cantonese', '#chinese'],
	JA: ['ja', 'jp', 'japanese', 'japan', 'japones', 'japon'],
	KR: ['ko', 'korean', 'korea', 'kr', 'hangul', '한국어'],
	RU: ['ru', 'russian', 'русский', 'россия', 'рус', 'руссия', 'английский russian'],
	FR: ['fr', 'french', 'français', 'francaise', 'franch', 'francés'],
	DE: ['de', 'german', 'deutsch', 'deu', 'ger', 'gernan', 'deutsch fränkisch'],
	ES: ['es', 'spanish', 'español', 'espanish', 'españa', 'castellano', 'espanol'],
	PT: ['pt', 'portuguese', 'portugues', 'português', 'portuges', 'brasil', 'brasileiro', 'língua portuguesa'],
	AR: ['ar', 'arabic', 'عربي', 'اللغة العربية', 'المملكة العربية السعودية', 'اللغة'],
	EN: ['en', 'english', 'american english', 'british english', 'englisg', 'engilsh', 'engllish', 'englsh', 'englsih', 'english/']
};

function normalizeLanguageTag(raw) {
	const value = raw.toLowerCase().trim();
	for (const [code, keywords] of Object.entries(languageMap)) {
		for (const keyword of keywords) {
			const pattern = new RegExp(`\\b${keyword}\\b`, 'i');
			if (pattern.test(value)) return code;
		}
	}
	return 'OTHERS'; // 无法识别或混合语种
}

const CARTO_DARK = 'https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json';

const ARCGIS_SATELITE = {
	version: 8,
	sources: {
		worldImagery: {
			type: 'raster',
			tiles: [
				'https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}'
			],
			tileSize: 256
		}
	},
	layers: [{
		id: 'worldImagery-layer',
		type: 'raster',
		source: 'worldImagery',
		minzoom: 0,
		maxzoom: 18
	}]
}

const ARCGIS_DARK = {
	version: 8,
	sources: {
		worldImagery: {
			type: 'raster',
			tiles: [
				'https://services.arcgisonline.com/arcgis/rest/services/Canvas/World_Dark_Gray_Base/MapServer/tile/{z}/{y}/{x}'
			],
			tileSize: 256
		}
	},
	layers: [{
		id: 'worldImagery-layer',
		type: 'raster',
		source: 'worldImagery',
		minzoom: 0,
		maxzoom: 18
	}]
};

const BASESTYLES = {
	'carto-dark': CARTO_DARK,
	'dark-gray': ARCGIS_DARK,
	'satelite': ARCGIS_SATELITE
}

const CACHE_KEY = 'stations_cache';
const UPDATE_TIME_KEY = 'stations_updated';
const CACHE_TTL = 3600000 * 24;

export class MapManager {
	constructor(containerId, onPointClick) {
		this.containerId = containerId;
		this.onPointClick = onPointClick;
		this.CACHE_KEY = CACHE_KEY;
		this.UPDATE_TIME_KEY = UPDATE_TIME_KEY;
		this.CACHE_TTL = CACHE_TTL;
		this.map = null;
		this.popup = null;
		this.controller = null;
	}

	// 地图初始化
	init() {
		console.log('初始化地图...');
		this.showLoading();
		let baseMap = localStorage.getItem('baseMap') || 'dark-gray';
		this.map = new maplibregl.Map({
			container: this.containerId,
			center: [0, 0],
			zoom: 2,
			style: BASESTYLES[baseMap],
			antialias: true
		});
		this.map.on('load', () => {
			console.log('地图加载完成');
			this.setProjectionAndSky();
			this.addPulsingDotImage();
			this.addStationLayer();
			this.addHeatLayer();
			this.addHighLightLayer();
			this.bindMapEvents();

			const lastUpdate = parseInt(localStorage.getItem(this.UPDATE_TIME_KEY) || '0');
			const cachedData = localStorage.getItem(this.CACHE_KEY);
			const cacheValid = cachedData && (Date.now() - lastUpdate < this.CACHE_TTL);
			if (cacheValid) {
				const featuresList = JSON.parse(cachedData);
				this.map.getSource('stations').setData({
					type: 'FeatureCollection',
					features: featuresList
				});
				console.log(`已从缓存加载电台数据共${featuresList.length}条`);
			} else {
				this.fetchAndCache();
			}
			//移除加载提示动画
			this.hideLoading();
		});
	}

	// 添加脉冲点图片
	addPulsingDotImage() {
		console.log('添加脉冲点图像');
		const size = 200;
		const map = this.map;
		const pulsingDot = {
			width: size,
			height: size,
			data: new Uint8Array(size * size * 4),
			onAdd() {
				const canvas = document.createElement('canvas');
				canvas.width = this.width;
				canvas.height = this.height;
				this.context = canvas.getContext('2d');
			},
			render() {
				const duration = 1000;
				const t = (performance.now() % duration) / duration;
				const radius = (size / 2) * 0.3;
				const outerRadius = (size / 2) * 0.7 * t + radius;
				const context = this.context;
				context.clearRect(0, 0, this.width, this.height);
				context.beginPath();
				context.arc(this.width / 2, this.height / 2, outerRadius, 0, Math.PI * 2);
				context.fillStyle = `rgba(255, 200, 200,${1 - t})`;
				context.fill();
				context.beginPath();
				context.arc(this.width / 2, this.height / 2, radius, 0, Math.PI * 2);
				context.fillStyle = 'rgba(255, 100, 100, 1)';
				context.strokeStyle = 'white';
				context.lineWidth = 2 + 4 * (1 - t);
				context.fill();
				context.stroke();
				this.data = context.getImageData(0, 0, this.width, this.height).data;
				map.triggerRepaint();
				return true;
			}
		};
		this.map.addImage('pulsing-dot', pulsingDot, { pixelRatio: 2 });
	}

	// 设置投影和天空
	setProjectionAndSky() {
		console.log('设置地球投影和天空背景');
		this.map.setProjection({ type: 'globe' });
		this.map.setSky({ 'atmosphere-blend': 1.0 });
	}

	// 高亮层
	addHighLightLayer() {
		console.log('添加高亮图层');
		this.map.addSource('highlight-source', {
			type: 'geojson',
			data: { type: 'FeatureCollection', features: [] }
		});
		this.map.addLayer({
			id: 'highlight-layer',
			type: 'symbol',
			source: 'highlight-source',
			layout: { 'icon-image': 'pulsing-dot', 'icon-size': 0.5 }
		});
	}

	// 电台点图层
	addStationLayer() {
		console.log('添加电台图层');
		this.map.addSource('stations', {
			type: 'geojson',
			data: { type: 'FeatureCollection', features: [] },
			cluster: false,
			clusterRadius: 25,
			clusterMaxZoom: 5
		});
		// this.map.addLayer({
		// 	id: 'clusters',
		// 	type: 'circle',
		// 	source: 'stations',
		// 	filter: ['has', 'point_count'],
		// 	paint: {
		// 		'circle-color': '#a5a5a5',
		// 		'circle-stroke-color': '#a8a8a8',
		// 		'circle-stroke-width': 1,
		// 		'circle-radius': [
		// 			'step',
		// 			['get', 'point_count'],
		// 			3, 100, 3, 750, 3
		// 		]
		// 	}
		// });
		this.map.addLayer({
			id: 'radio-point-layer',
			type: 'circle',
			source: 'stations',
			minzoom: 5,
			filter: ['!', ['has', 'point_count']],
			paint: {
				'circle-color': ['get', 'color'], // 实心圆颜色不变
				'circle-radius': 4,
				'circle-stroke-color': [
					'case',
					['==', ['typeof', ['get', 'color']], 'string'],
					['concat', ['get', 'color'], '30'], // hex + alpha = 半透明（80 ≈ 0.5）
					'#cccccc' // fallback
				],
				'circle-stroke-width': 6
			}
		});
	}

	addHeatLayer() {
		this.map.addLayer({
			id: 'radio-heat-layer',
			type: 'heatmap',
			source: 'stations',
			maxzoom: 7,
			paint: {
				'heatmap-weight': [
					'interpolate', ['exponential', 2],
					['get', 'clickcount'],
					0, 0,
					18554, 1
				],
				'heatmap-intensity': [
					'interpolate',
					['linear'],
					['zoom'],
					0, 1,
					10, 3
				],
				'heatmap-color': [
					'interpolate',
					['linear'],
					['heatmap-density'],
					0.0, 'rgba(0,0,0,0)',               // 透明消隐
					0.2, 'rgb(25,25,112)',              // 深海军蓝
					0.4, 'rgb(72,61,139)',              // 暗紫蓝
					0.6, 'rgb(138,43,226)',             // 蓝紫电感
					0.8, 'rgb(75,0,130)',               // 靛蓝聚焦
					1.0, 'rgb(255,0,255)'               // 紫粉高能
				]
				,
				'heatmap-radius': [
					'interpolate',
					['linear'],
					['zoom'],
					0, 2,
					10, 20
				],
				'heatmap-opacity': 0.6
			}
		});

	}

	// 数据拉取与缓存
	fetchAndCache() {
		console.log('开始拉取数据并写入缓存...');
		this.controller = new AbortController();
		const signal = this.controller.signal;

		const batchRequests = [];
		const featuresList = [];
		let offset = 0;
		let max_count = 0;
		for (let i = 1; i <= 6; i++) {
			let limit = 500 * i;
			const url = `https://api.radiodb.fr/json/stations/search?offset=${offset}&limit=${limit}&hidebroken=true&has_geo_info=true&order=clickcount&reverse=true&fields=name,stationuuid,geo_lat,geo_long`;
			offset += limit;
			const request = fetch(url, { signal })
				.then(res => res.json())
				.then(data => {
					const newFeatures = data.map(station => {
						const category = normalizeCategory(station.tags);
						const langcode = normalizeLanguageTag(station.language + ' ' + station.country + ' ' + station.countrycode);
						const color = TAG_COLORS[category];
						max_count = Math.max(+station.clicktrend, max_count)
						return {
							type: 'Feature',
							id: station.stationuuid,
							geometry: {
								type: 'Point',
								coordinates: [+station.geo_long, +station.geo_lat]
							},
							properties: {
								name: station.name,
								stationuuid: station.stationuuid,
								favicon: station.favicon,
								url: station.url,
								// tags: station.tags,
								// country: station.country,
								// countrycode: station.countrycode,
								geo_lat: station.geo_lat,
								geo_long: station.geo_long,
								langcode,
								category,
								color
							}
						}
					});
					featuresList.push(...newFeatures);
					this.map.getSource('stations').setData({
						type: 'FeatureCollection',
						features: featuresList
					});
					console.log(`成功获取 ${newFeatures.length} 条电台数据`);
				}).catch(err => {
					if (err.name === 'AbortError') {
						console.warn(`请求第${i}批被取消`);
					} else {
						console.error(`请求第${i}批数据失败:`, err);
					}
				});
			batchRequests.push(request);
		}
		Promise.allSettled(batchRequests).then((results) => {
			// const hasError = results.some(r => r.status === 'rejected' && r.reason.name !== 'AbortError');
			// const wasAborted = results.some(r => r.status === 'rejected' && r.reason.name === 'AbortError');

			// if (hasError || wasAborted) {
			// 	console.warn('⚠️ 存在失败或取消的请求，本轮不写入缓存');
			// 	return;
			// }

			// 如果全部成功，才写入缓存
			console.log('✅ 所有请求成功，写入缓存');
			localStorage.setItem(this.CACHE_KEY, JSON.stringify(featuresList));
			localStorage.setItem(this.UPDATE_TIME_KEY, Date.now().toString());
			console.log(`写入缓存成功，共${featuresList.length}条`)
		}).catch(error => {
			console.error('批量请求处理异常:', error);
		});
	}

	// 事件绑定
	bindMapEvents() {
		console.log('绑定地图事件');
		this.map.on('mouseenter', 'radio-point-layer', () => {
			this.map.getCanvas().style.cursor = 'pointer';
		});
		this.map.on('mouseleave', 'radio-point-layer', () => {
			this.map.getCanvas().style.cursor = '';
		});
		this.map.on('click', 'radio-point-layer', (e) => {
			console.log('点击事件');
			const feature = e.features[0];
			const coordinates = feature.geometry.coordinates.slice();
			const props = feature.properties;
			console.log('点击点位:', props.name, coordinates);
			// this.highLightStation(...coordinates, props);
			if (this.onPointClick) this.onPointClick(props);
		});

	}

	highLightStation(long, lat, props) {
		console.log('highLightStation', long, lat, props);
		const coordinates = [+long, +lat]
		const feature = {
			type: 'Feature',
			id: props.stationuuid,
			geometry: {
				type: 'Point',
				coordinates
			},
			properties: props
		};
		const highlightData = {
			type: 'FeatureCollection',
			features: [feature]
		};
		if (this.map.getSource('highlight-source')) this.map.getSource('highlight-source').setData(highlightData);
		// 居中定位到点击点
		this.map.flyTo({
			center: coordinates,
			// zoom: 3, // 可根据需要调整缩放级别
			speed: 1.2, // 动画速度
			curve: 1.4, // 动画曲线
			easing: (t) => t // 使用线性动画
		});
		const popupContent = `<div class="bubble-content">
				<span class="radio-name">${props.name}</span>
				<span class="radio-style">${props.country || ''}</span>
			</div>	
			`
		this.removePopup();
		this.popup = new maplibregl.Popup()
			.setLngLat(coordinates)
			.setHTML(popupContent)
			.addTo(this.map);
	}

	removePopup() {
		console.log('removePopup')
		if (this.popup) this.popup.remove();
	}
	unbindMapEvents() {
		console.log('解绑地图事件');
		if (!this.map) return;

		this.map.off('mouseenter', 'radio-point-layer');
		this.map.off('mouseleave', 'radio-point-layer');
		this.map.off('click', 'radio-point-layer');
	}

	setBaseStyle(style) {
		console.log('设置底图样式', style);
		if (!this.map) return;
		this.showLoading();
		const styleUrl = BASESTYLES[style];
		this.unbindMapEvents(); // 先解绑旧事件
		this.map.once('styledata', () => {
			console.log('style.load事件')
			// 重新添加图层
			this.setProjectionAndSky();
			this.addPulsingDotImage();
			this.addStationLayer();
			this.addHeatLayer();
			this.addHighLightLayer();
			this.bindMapEvents();

			// 恢复数据
			const lastUpdate = parseInt(localStorage.getItem(this.UPDATE_TIME_KEY) || '0');
			const cachedData = localStorage.getItem(this.CACHE_KEY);
			const cacheValid = cachedData && (Date.now() - lastUpdate < this.CACHE_TTL);
			if (cacheValid) {
				const featuresList = JSON.parse(cachedData);
				this.map.getSource('stations').setData({
					type: 'FeatureCollection',
					features: featuresList
				});
				console.log(`已从缓存加载电台数据共${featuresList.length}条`);
			} else {
				// 中断上一次请求
				if (this.controller) {
					console.log('取消上一次的请求');
					this.controller.abort();
				}
				this.fetchAndCache();
			}
			this.hideLoading()
		});
		this.map.setStyle(styleUrl);
	}

	/**
	 * 创建加载显示提示动画DOM
	 */
	showLoading() {
		let spinner = document.getElementById('map-loading-spinner');
		if (!spinner) {
			spinner = document.createElement('div');
			spinner.id = 'map-loading-spinner';
			document.body.appendChild(spinner);
		}
	}
	/**
	 * 移除加载提示动画DOM
	 */
	hideLoading() {
		const spinner = document.getElementById('map-loading-spinner');
		console.log('移除加载动画');
		if (spinner) spinner.remove();
	}
}